#!/usr/bin/python

'''
# CSV to C code. Generate a C-compilable array from values in a CSV file.
# Version 0.2 - July 3, 2012
# Copyright (C) 2012 Caimanics (http://www.caimanics.com/)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
'''

'''
# Changelog:
#
# June 27, 2012     /  0.1  /  pablo.bacho@caimanics.com
#   Created.
#
# July 3, 2012      /  0.2  / pablo.bacho@caimanics.com
#   Added elements count in generated code
#   File to array step before generating the output string
#   Bug fixes
#
'''

import argparse
import os.path
import datetime

# Parse command-line arguments
parser = argparse.ArgumentParser(description='Parse an array of numbers in CSV format to C static source code')
parser.add_argument('input', help='Input file') # Source filename is mandatory
parser.add_argument('-o', '--output', help='Output file') # Output filename
parser.add_argument('-n', '--name', help='Variable name')
parser.add_argument('-t', '--type', help='Variable type (default int)', default='int')
parser.add_argument('-l', '--lined', help='Line delimiter', default='\n')
parser.add_argument('-w', '--wordd', help='Word delimiter', default=',')
parser.add_argument('-q', '--quiet', help='No output on stdout (except errors)', action='store_true', default=False)
args = parser.parse_args()

if args.quiet == False:
    print '''
CSV to C code. Version 0.1 - June 27, 2012
Copyright (C) 2012 Caimanics (http://www.caimanics.com/)

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.'''

# input filename
ifilename = args.input

# Guess the output filename given the input arguments
if args.output == None: # If output file isn't specified, the input filename will be used
    ifilenamesplitted = ifilename.partition('.')
    ofilename = ifilenamesplitted[0] + '.c'
else: # Use the output filename, if existing
    ofilename = args.output
    if ofilename.endswith('.c') == False:
        if args.quiet == False:
            print 'Warning: output filename doesn\'t have .c extension\n'

# Variable identifier
if args.name == None:
    ofilenamesplitted = ofilename.partition(".")
    varname = ofilenamesplitted[0]
else:
    varname = args.name

# Delimiters
if args.lined == None:
    lined = '\n'
else:
    lined = args.lined
    
if args.wordd == None:
    wordd = ','
else:
    wordd = args.wordd

# Check variable name for forbidden characters
splitvar = varname.split("_")
for x in splitvar:
    if x.isalnum() == False:
        print 'Error: variable names should only contain [a-zA-Z0-9_]'
        exit(-1)

# Check if input file exists
if os.path.exists(ifilename) == False:
    print 'Error: unable to open ' + ifilename
    exit(-1)
if os.path.isfile(ifilename) == False:
    print 'Error: unable to open ' + ifilename
    exit(-1)

# Open source file and store its content in memory
ifile = open(ifilename, 'r')
inputfilecontent = ifile.read()
ifile.close()

inputfilecontentbyrow = inputfilecontent.splitlines()
data = list()

# Unidimensional vertical array
if inputfilecontentbyrow[0].find(wordd) == -1:
    for word in inputfilecontentbyrow:
        if word.isdigit():
            data.append(int(word))
# Unidimensional horizontal array
elif inputfilecontentbyrow[1] == '':
    wordslist = inputfilecontentbyrow[0].split(wordd)
    for word in wordslist:
        if word.isdigit():
            data.append(int(word))
# Bidimensional array
else:
    for irow in inputfilecontentbyrow:
        if(len(irow) > 0):
            dataline = list()
            for value in wordslist:
                if(value.isdigit()):
                    dataline.append(int(value))
            data.append(dataline)

# Create the output buffer and start filling it
outputfilecontent = '''/* * * * * * * * * * * * * * * * * * * * *
 * Look up table for "''' + varname + '''"
 * ''' + datetime.datetime.now().strftime("%Y-%m-%d %H:%M") + '''
 * Generated with csv2c script from caimanics.com.
 * This code is generated in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * * * * * * * * * * * * * * * * * * * */
\n'''

# Unidimensional array
if data[0].__class__ == int:
    outputfilecontent += args.type + ' ' + varname + '[' + str(len(data)) + '] = {\n'
    for value in data:
        outputfilecontent += str(value) + ', '
    outputfilecontent = outputfilecontent[:-2] + '\n};\n'
# Bidimensional array
else:
    outputfilecontent += args.type + ' ' + varname + '[' + str(len(data)) + '][' + str(len(data[0])) + '] = {\n'
    for irow in data:
        outputfilecontent += '{'
        for value in irow:
            outputfilecontent += str(value) + ', '
        outputfilecontent = outputfilecontent[:-2] + '},\n'
    outputfilecontent = outputfilecontent[:-2] + '\n};\n'
    
# Save output to file
ofile = open(ofilename, 'w')
ofile.write(outputfilecontent)
ofile.close()
